package cn.aion.crawlers;

import cn.aion.dao.AnchorChannelDAO;
import cn.aion.dao.AnchorDataDAO;
import cn.aion.model.AnchorChannel;
import cn.aion.model.AnchorData;
import cn.aion.model.YoukuPage;
import cn.wanghaomiao.seimi.annotation.Crawler;
import cn.wanghaomiao.seimi.http.SeimiAgentContentType;
import cn.wanghaomiao.seimi.struct.Request;
import cn.wanghaomiao.seimi.struct.Response;
import cn.wanghaomiao.seimi.def.BaseSeimiCrawler;
import cn.wanghaomiao.xpath.model.JXDocument;
import cn.wanghaomiao.xpath.model.JXNode;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.util.HtmlUtils;



import java.util.List;

/**
 *
 * Created by 虚空之翼 on 2016/11/23.
 */
@Crawler(name = "channel", useCookie = true, useUnrepeated = false, delay = 1)
public class Channel extends BaseSeimiCrawler {
    @Autowired
    private AnchorChannelDAO anchorChannelDAO;
    @Autowired
    private AnchorDataDAO anchorDataDAO;

    @Value("${seimiAgentHost}")
    private String seimiAgentHost;
    @Value("${seimiAgentPort}")
    private int seimiAgentPort;
    @Override
    public String seimiAgentHost() { return this.seimiAgentHost; }
    @Override
    public int seimiAgentPort() { return this.seimiAgentPort; }

    @Value("${youku.username}")
    private String youkuUsername;
    @Value("${youku.password}")
    private String youkuPassword;

    @Override
    public String[] startUrls() {
        //两个是测试去重的
        return new String[]{"http://www.van-cool.com/admin/base/scan"};
    }

    // 分页数据标识
    public static int dataFlag = 1;
    public static int pn = 1;
    public static int loginTotal = 0;
    public static Boolean isLogin = true;

    @Override
    public void start(Response response) {
        logger.info("启动优酷自频道扫描程序");
//        login();
        main();
    }

    /**
     * 模拟优酷登入
     */
    public void login() {
        try {
            logger.info("自动登入优酷帐号");
//            String userName = "eoaion@gmail.com";
//            String password = "yk146937";
            String userName = youkuUsername;
            String password = youkuPassword;
            Request seimiAgentReq;
            seimiAgentReq = Request.build("https://account.youku.com", "loginSuccess").setSeimiAgentUseCookie(true)
                    .setSeimiAgentScript("document.getElementById('YT-ytaccount').value = '"+userName+"';document.getElementById('YT-ytpassword').value = '"+password+"';document.getElementById('YT-nloginSubmit').click();")
                    .useSeimiAgent().setSeimiAgentRenderTime(3000);
            push(seimiAgentReq);
            // 异步等待登入结果
            Thread.sleep(3000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void loginSuccess(Response response) {
        JXDocument doc = response.document();
        try {
            String err = StringUtils.join(doc.sel("//div[@id='YT-errorTips']/text()"),"");
            loginTotal++;
            if (err.equals("")) {
                isLogin = true;
                loginTotal = 0;
                // 初始化重新扫描
                pn--;
//                pn = pn < 1 ? 1 : pn;
                main();
                logger.info("登入成功");
            } else {
                isLogin = false;
                if (loginTotal <= 3) {
                    login();
                } else {
                    logger.info("登入超过次数，稍后再试！");
                }
                logger.info("登入失败，错误：{}", err);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Scheduled(cron = "0 0 14,18,22 * * ?")
    public void main() {
        String baseUrl = "http://www.youku.com/u/originalRanking/channel/0/rank/0/ajaxget/1/pn/";
        try {
            Request seimiAgentReq;
            do {
                logger.info("扫描分页：{}", baseUrl+pn);
                seimiAgentReq = Request.build(baseUrl+pn, "getList").setSeimiAgentUseCookie(true)
                        .useSeimiAgent().setSeimiAgentRenderTime(1000);
                push(seimiAgentReq);

                Thread.sleep(2000);
                pn++;
            } while (dataFlag != 0 && pn <= 200 && isLogin);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void getList(Response response) {
        String docString = response.getContent();
        // 判断是否需要重新登入
        if (!docString.contains("dataflag")) {
            isLogin = false;
            if (loginTotal <= 3) {
                login();
            } else {
                logger.info("登入超过次数，稍后再试！");
            }
        } else {
            // 解析源文件（需要即时变通）
//        YoukuPage page = JSON.parseObject(docString, YoukuPage.class);
//        dataFlag = page.getDataflag();
            String newString = docString.substring(docString.indexOf("{\""),docString.indexOf("\"}")+2);

            String dataflagStr = newString.substring(newString.indexOf("{\"dataflag\":")+12, newString.indexOf(",\"html\":\""));
            String html = newString.substring(newString.indexOf("\"html\":\"")+8, newString.indexOf("\"}"));
            html = HtmlUtils.htmlUnescape(html);
            html = StringEscapeUtils.unescapeJava(html).replaceAll("\r\n", "").replaceAll("\"\"","\"");
            dataFlag = Integer.parseInt(dataflagStr);
            if (dataFlag != 0) {
                try {
                    JXDocument pageDocument = new JXDocument(html);
                    List<JXNode> channels = pageDocument.selN("//li");
                    for (JXNode channel : channels) {
                        String channelStr = channel.toString();
                        channelStr = HtmlUtils.htmlUnescape(channelStr);
                        channelStr = StringEscapeUtils.unescapeJava(channelStr).replaceAll("\r\n", "").replaceAll("\"\"","\"");

                        JXDocument jxDocument = new JXDocument(channelStr);
                        String name = StringUtils.join(jxDocument.sel("//div[@class='userInfo']/h3/a/text()"),"");
                        String header = StringUtils.join(jxDocument.sel("//div[@class='userInfo']/a/img/@src"),"");
                        String rankNum = StringUtils.join(jxDocument.sel("//label[@class='rankNum']/text()"),"");
                        String rankNumLarge = StringUtils.join(jxDocument.sel("//label[@class='rankNum-large']/text()"),"");
                        String href = StringUtils.join(jxDocument.sel("//div[@class='userInfo']/a[first()]/@href"),"");
                        String detail = StringUtils.join(jxDocument.sel("//div[@class='userInfo']/p/text()"),"");
                        logger.info("[{}]{} - {}", rankNum+rankNumLarge, name, href);

                        AnchorChannel anchorChannel = anchorChannelDAO.selectOneByName(name);
                        if (anchorChannel == null) {
                            AnchorChannel newChannel = new AnchorChannel();
                            newChannel.setName(name);
                            newChannel.setHeader(header);
                            newChannel.setYoukuUrl(href);
                            newChannel.setDetail(detail);
                            anchorChannelDAO.save(newChannel);
                        }
                        href = href.replace("com/u/", "com/i/");
                        push(new Request(href+"/videos", "getInfo"));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }


    }

    /**
     * 获取主播详细资料
     * @param response
     */
    public void getInfo(Response response){
        JXDocument doc = response.document();
        try {
            String name = StringUtils.join(doc.sel("//a[@class='username']/@title"),"");
            String header = StringUtils.join(doc.sel("//a[@class='user-avatar']/img/@src"),"");
            String detail = StringUtils.join(doc.sel("//span[@class='desc']/text()"),"");
            String play = StringUtils.join(doc.sel("//li[@class='vnum']/@title"),"");
            String fans = StringUtils.join(doc.sel("//li[@class='snum']/@title"),"");
            String video = StringUtils.join(doc.sel("//div[@class='YK-box']/div/div[@class='title']/span/text()"),"");
            logger.info("{}[{}] - 播放：{} - 粉丝：{}", name, response.getUrl(), play, fans);
            // 等级排行榜
            // 判断是否厂商频道（厂商无数据）
            int siteRank = 0;
            int channelRank = 0;
            int channel = 0;
//            String check = StringUtils.join(doc.sel("//ul[@class='rank-data']/li/a/@href"),"");
//            if (!play.equals("")) {
//                String siteHref = doc.sel("//ul[@class='rank-data']/li/a/@href").get(0).toString();
//                String channelHref = doc.sel("//ul[@class='rank-data']/li/a/@href").get(1).toString();
//                String siteRankStr = doc.sel("//ul[@class='rank-data']/li/a/span/text()").get(1).toString();
//                String channelRankStr = doc.sel("//ul[@class='rank-data']/li/a/span/text()").get(3).toString();
//                String[] hrefArr = channelHref.split("/");
//                siteRank = Integer.parseInt(siteRankStr);
//                channelRank = Integer.parseInt(channelRankStr);
//                channel = Integer.parseInt(hrefArr[6]);
//            } else {
//                String title = StringUtils.join(doc.sel("//meta[@name='title']/@content"),"");
////                String title = doc.sel("//meta[@name='title']/@content")toString();
//                logger.info("厂商频道：{} - {}", title , response.getUrl());
//            }

//            String last = doc.selN("//span[@class='v-publishtime']/text()").get(0).toString();
            String last = "";
            List<JXNode> lastData = doc.selN("//span[@class='v-publishtime']/text()");
            if (!lastData.isEmpty()) {
                last = lastData.get(0).toString();
            }

            AnchorChannel anchorChannel = anchorChannelDAO.selectOneByName(name);
            if (anchorChannel != null) {
                anchorChannel.setDetail(detail);
                anchorChannel.setHeader(header);
                anchorChannel.setSiteRank(siteRank);
                anchorChannel.setChannelRank(channelRank);
                anchorChannel.setChannel(channel);

                // 处理相关不稳点的数据
                Long playTotal = 0L;
                int fansTotal = 0;
                int videoTotal = 0;
                if (!play.equals("")) {
                    playTotal = Long.parseLong(play.replaceAll(",", ""));
                    anchorChannel.setPlayTotal(playTotal);
                }
                if (!fans.equals("")) {
                    fansTotal = Integer.parseInt(fans.replaceAll(",", ""));
                    anchorChannel.setFansTotal(fansTotal);
                }
                if (!video.equals("")) {
                    String videoStr = video.replaceAll(",", "").replace("(", "").replace(")", "");
                    if (videoStr.indexOf("万") > 0) {
                        videoTotal = (int)Float.parseFloat(videoStr.replace("万", "")) * 10000;
                    } else {
                        videoTotal = Integer.parseInt(videoStr);
                    }
                    anchorChannel.setVideoTotal(videoTotal);
                }

                if (last.indexOf("小时前") > 0) {
                    anchorChannel.setLastUpload(1);
                }
                anchorChannelDAO.update(anchorChannel);

                // 计算增量
                int playAdd = 0;
                int fansAdd = 0;
                int videoAdd = 0;
                AnchorData preAnchorData = anchorDataDAO.selectOnePrevious(anchorChannel.getId());
                if (preAnchorData != null) {
                    playAdd = (int)(playTotal - preAnchorData.getYoukuPlayTotal());
                    fansAdd = fansTotal - preAnchorData.getYoukuFansTotal();
                    int diff = videoTotal - preAnchorData.getYoukuVideosTotal();
                    videoAdd = diff  > 0 ? diff : 0;
                }

                // 添加统计信息
                AnchorData todayAnchorData = anchorDataDAO.selectOneToday(anchorChannel.getId());
                if (todayAnchorData == null) {
                    AnchorData data = new AnchorData();
                    data.setChannelId(anchorChannel.getId());
                    data.setYoukuPlayTotal(playTotal);
                    data.setYoukuFansTotal(fansTotal);
                    data.setYoukuVideosTotal(videoTotal);
                    data.setYoukuPlayAdd(playAdd);
                    data.setYoukuFansAdd(fansAdd);
                    data.setYoukuVideosAdd(videoAdd);

                    data.setPlayTotal(playTotal);
                    data.setFansTotal(fansTotal);
                    data.setType(1);

                    if (last.indexOf("小时前") > 0) {
                        data.setLastUpload(1);
                    }
                    anchorDataDAO.saveYouku(data);
//                    anchorDataDAO.updateTotal(data.getId());
////                    logger.info("{}新增数据：{}，{}，{}，{}", data.getId(),playTotal, playAdd, fansTotal, fansAdd);
                } else {
                    if (playTotal != 0) {
                        todayAnchorData.setYoukuPlayTotal(playTotal);
                        todayAnchorData.setYoukuPlayAdd(playAdd);
                    }
                    if (fansTotal != 0) {
                        todayAnchorData.setYoukuFansTotal(fansTotal);
                        todayAnchorData.setYoukuFansAdd(fansAdd);
                    }
                    todayAnchorData.setYoukuVideosTotal(videoTotal);
                    todayAnchorData.setYoukuVideosAdd(videoAdd);
                    anchorDataDAO.updateYouku(todayAnchorData);

                    // 更新总数
                    anchorDataDAO.updateTotal(todayAnchorData.getId());
                }
                // 更新优酷频道总数
                anchorChannelDAO.updateYoukuTotal(anchorChannel.getId(), playTotal, fansTotal, videoTotal);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
